package br.academia.negocio;

import org.hibernate.HibernateException;

import br.academia.arq.dao.AlunoDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Aluno;
import br.academia.util.Validador;

/** 
 * Processador para validação de negócio de operações
 * relacionadas a Aluno
 * 
 * @see Aluno
 */
public class AlunoProcessador extends AbstractProcessador<Aluno>{

	@Override
	public void execute(TipoOperacao operacao, Aluno obj) throws NegocioException{
		try {
			if(operacao.equals(CADASTRAR)){
				validarCadastro(obj);
				cadastrar(obj);
			}else if(operacao.equals(ALTERAR)){
				validarAlteracao(obj);
				alterar(obj);
			}else if(operacao.equals(REMOVER)){
				validarRemocao(obj);
				remover(obj);
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new NegocioException("Não foi possível realizar a operação. Contate a administração do sistema.");
		} catch (DAOException e) {
			throw new NegocioException(e.getMessage());
		}
	}
	
	/**
	 * Método que valida se o nome setado em um Aluno já tem um correspondente
	 * com relação ao email, no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void validarEmail(Aluno obj) throws NegocioException, HibernateException, DAOException{
		AlunoDAO dao = null;
		boolean erro = false;
		
		try {
			dao = getDAO(AlunoDAO.class);
			
			Aluno aluno = dao.findAlunoByEmail(obj.getEmail());
			
			if(!Validador.isEmpty(aluno)){
				if(aluno.getId() != obj.getId()){
					erro = true;
				}
			}
			
			if(erro){
				throw new NegocioException("Um outro Aluno já foi cadastrado com o email \"" + obj.getEmail() + "\".");
			}
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para o cadastro
	 * de um Aluno novo no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarCadastro(Aluno obj) throws HibernateException, NegocioException, DAOException{
		validarEmail(obj);
	}
	
	/**
	 * Método que insere um Aluno no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void cadastrar(Aluno obj) throws NegocioException, HibernateException, DAOException{
		AlunoDAO dao = null;
		
		try {
			dao = getDAO(AlunoDAO.class);
			
			dao.save(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a alteração
	 * de um Aluno no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarAlteracao(Aluno obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Aluno inválido.");
		}else{
			AlunoDAO dao = null;
			Aluno aluno = null;
			
			try {
				dao = getDAO(AlunoDAO.class);
				
				aluno = dao.findAlunoByNome(obj.getNome());
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(!Validador.isEmpty(aluno)){
				validarEmail(obj);
			}
		}
	}
	
	/**
	 * Método que atualiza um Aluno no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void alterar(Aluno obj) throws NegocioException, HibernateException, DAOException{
		AlunoDAO dao = null;
		
		try {
			dao = getDAO(AlunoDAO.class);
			
			dao.update(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a remoção
	 * de um Aluno no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarRemocao(Aluno obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Aluno inválido.");
		}else{
			AlunoDAO dao = null;
			Aluno Aluno = null;
			
			try {
				dao = getDAO(AlunoDAO.class);
				
				Aluno = dao.findByPrimaryKey(obj.getId(), Aluno.class);
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(Validador.isEmpty(Aluno)){
				throw new NegocioException("Não foi possível encontrar o Aluno selecionado no nosso banco de dados.");
			}
		}
	}
	
	/**
	 * Método que remove um Aluno do banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void remover(Aluno obj) throws NegocioException, HibernateException, DAOException{
		AlunoDAO dao = null;
		
		try {
			dao = getDAO(AlunoDAO.class);
			
			dao.delete(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
}
